package cn.edu.sdjzu.xg.kcsj.util;

import cn.edu.sdjzu.xg.kcsj.exception.BysjException;
import cn.edu.sdjzu.xg.kcsj.security.User;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;

import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;

public class JwtUtil {
    //秘钥,生产环境中应动态化
    private static final String SECRETE = "20221224";
    //指定算法为HMAC256，并传入一个秘钥，形成加密算法
    private static Algorithm algorithm = Algorithm.HMAC256(SECRETE);
    public static String createToken(User user, int expire) {
        // jwt对象
        JWTCreator.Builder builder = JWT.create();
        // 过期时间 = 当前日期 + expire
        // LocalDateTime dateTime= LocalDateTime.now().plusMinutes(expire);
        Calendar dataTimeInstance = Calendar.getInstance();
        // 过期时间为现在开始的7天后
        // instance.add(Calendar.DATE, 7);
        // 过期时间为现在开始的expire分钟后
        dataTimeInstance.add(Calendar.MINUTE, expire);
        String token = builder
                //可以接受默认值，不设置header，
                //将当前参与者的id（代表当前用户）和name（显示在前端）写入Token的载荷中
                .withClaim("currentUserId", user.getId())
                .withClaim("currentUserName", user.getName())
                //Date类式表达时间
                //.withExpiresAt(new Date(new Date().getTime() + (1000 * 60 * expire)))
                //LocalDateTime类式表达时间
                //.withExpiresAt(Date.from(dateTime.atZone( ZoneId.systemDefault()).toInstant()))
                //Calendar类式表达时间
                .withExpiresAt(dataTimeInstance.getTime())
                //执行加密算法
                .sign(algorithm);
        return token;
    }

    // 解析token
    public static DecodedJWT verifyToken(String token) throws BysjException {
        if (token == null){
            throw  new BysjException("没发现令牌");
        }
        // 验证令牌
        try {
            DecodedJWT verify = JWT.require(algorithm).build().verify(token);
            return verify;
        }catch (SignatureVerificationException e){
            throw  new BysjException("权限令牌签名不一致");
        }catch (TokenExpiredException e){
            throw  new BysjException("权限令牌过期");
        }catch (InvalidClaimException e){
            throw new BysjException("权限令牌内容错误");
        }catch (Exception e){
            throw new BysjException("不合法的登录请求");
        }
    }

    // 从request中获取"token"为名的令牌
    public static DecodedJWT verifyToken(HttpServletRequest request) throws BysjException {
        return verifyToken(request,"token");
    }

    // 从request中获取tokenName为名的令牌
    public static DecodedJWT verifyToken(HttpServletRequest request, String tokenName) throws BysjException {
        return verifyToken(request.getHeader(tokenName));
    }
}
